飛び入り参加した FOSS4G アドベントカレンダー(その2)のエントリです。
今日と明日(2016年12月13、14)、芝公園のプリンスパークタワーで開催されているSalesForce World Tour Tokyo 2016 にサムライシステムとして出展してます。
SalesForce上で使えるカンタンな地図アプリとして「カスタマーコンパス」という製品を出してます。
「カスタマーコンパス」はGoogleMapsAPIをベースとして使っていて、OpenStreetMapや地理院地図は標準で表示できるようになってます。
ゼンリンさんには展示会用限定でライセンスを頂きました。ありがとうございました!
なお、仕様は契約者以外非公開の機密情報なので、可能な範囲で書いています。
まず初めに、制約事項。
GoogleMapsAPIの利用規約で、GoogleMapsの地図タイルはGoogleMaps API経由以外で、タイルだけ取ってくることができません。
結局、システムの異なる二つの地図を両方とも出すしかない。
これがあるので、サブマップ(地図の中に小さな地図がある)タイプにするか、二つ並べてツインマップにするか、そういう方向性で考えないといけない。
そういえば、OpenLayersやLeafletといったAPIでGoogleMaps(地図タイル画像の直接呼出しがNG)使うトリックがいくつかあったなあ、、、とか、
y2blog『OpenLayers 3 とGoogle Mapsを組み合わせてみる』OpenLayers e examples "Google Maps integration example"
そのあたりを参考に、いろいろ考えた末の方針が
1) 同サイズのGoogleMapsとゼンリン地図を用意する。
2) 位置、ズームレベルを同期させる。
3) GoogleMapsの背後にゼンリン地図を配置する。
4) 住宅地図を表示するときは、GooleMaps側で呼ぶタイルを完全に透明な「透過」タイルにして、住宅地図が透けて見えるようにする!!
ここで
- ゼンリン住宅地図のDIVのZ-indexを -1 にセット
- GoogleMapsで背後の壁紙になっている document.getElementById('map').firstChild のstyle.backgroundColor 属性を"transparent" にする
これで、GoogleMapsのコントロールやマーカーはそのまま前面に、背景だけ住宅地図になる。
ここで問題発生!!
マーカーの位置が合わないと思ったら、ゼンリンの住宅地図APIのズームレベル(縮尺)の取り方が、一般的な「地図タイル」の仕様とは異なる仕様でした!!
一般的というのはGoogleMapsや、OSMや、地理院のタイルのように、一つのタイルを4分割すると次のズームレベルに、という具合に縮尺比率が2倍、2倍に詳細になっていく仕様。X,とYの定義に若干の違いがあるけど、基本的なタイル地図の仕組みは同じなのでGoogleMapsでもOpenLayersでもLeafletでも(利用規約はともかく技術的には)同じように使える。
ところがゼンリンAPIは、2倍ずつではなく、ズームレベルに応じて縮尺がもう少し細かい。
横に並べて使うにはいいんだけど、背後に配置して「なんちゃってシームレス」にするには、ズームレベルがぴったりあってないと、マーカーの位置がずれる!!
ここでいろいろ試行錯誤して、GoogleMapsのズームレベル19(のみ)と、住宅地図のあるレベルの縮尺だけが偶然にもほぼ完全に一致することが判明。厳密には投影法が違うので、画面上見た目がほぼほぼ一致しているだけなんだけれど、実用上は十分。
ちなみに、他のズームレベル同士で縮尺が合うものは一つも無かった。
という訳で、カスタマーコンパスで「ゼンリン住宅地図」に切り替えた時は問答無用でGoogle側のズームレベル19に固定することでOK。
結果、ズームレベル19のとき限定ですが、一見GoogleMapsAPIにその地図を組み込んだの???と思うくらい「なんちゃってシームレス」な住宅地図を、利用規約にも違反せずに実装できました!!
タイルとGoogleMapの背景色を透明にすれば背景が透けて見えるので、背景を誰かの顔写真にしておいて、チェックインした位置情報のタイルだけ透明にすれば
『ジオ版 アタック25 その人物の名は!』
みたいなゲームできるな。。。。